package com.distribute.application.admin;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.distribute.framework.core.web.helper.Utils;
import com.distribute.framework.plugin.Cache;
import com.distribute.framework.plugin.Notify;

@WebServlet(urlPatterns = "/admin/comet", asyncSupported = true)
public class CometServlet  extends HttpServlet {
 	private static final long serialVersionUID = -8685285401859800066L;
 	
 	private static final long wait_time_seconds = 10;//等待保留秒数

    static Map<String,AsyncContext> asyncContexts = new ConcurrentHashMap();

    @Override
    public void init() throws ServletException {
        super.init();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        AsyncContext asyncContext = req.startAsync();
        asyncContext.setTimeout(wait_time_seconds * 1000L);
        asyncContext.addListener(new AsyncListener(){
			@Override
			public void onComplete(AsyncEvent arg0) throws IOException {
				remove(arg0.getAsyncContext());
			}
			@Override
			public void onError(AsyncEvent arg0) throws IOException {
				remove(arg0.getAsyncContext());
			}
			@Override
			public void onStartAsync(AsyncEvent arg0) throws IOException {}
			@Override
			public void onTimeout(AsyncEvent arg0) throws IOException {
				remove(arg0.getAsyncContext());
			}
        });
        String sid = req.getSession().getId();
        asyncContext.getRequest().setAttribute("sid", sid);
        asyncContexts.put(sid,asyncContext);
    }

    protected void remove(AsyncContext asyncContext) {
    	String sid = (String) asyncContext.getRequest().getAttribute("sid");
    	asyncContexts.remove(sid);
	}
    
    
    public static void send(Object data,String... ids){
		if(ids.length==0){
			ids = asyncContexts.keySet().toArray(new String[]{});
		}
		synchronized (asyncContexts){
			for(String sid:ids){
				sendData(asyncContexts.get(sid),data);
			}
		}
	}
	public static void sendData(AsyncContext asyncContext,Object data){
		try {
			ServletResponse response = asyncContext.getResponse();
			response.setCharacterEncoding("UTF-8");
			PrintWriter writer = response.getWriter();
			writer.write(JSON.toJSONString(data));
			writer.flush();
			writer.close();
			asyncContext.complete();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
    public void destroy() {
        super.destroy();
    }
	
	
	static{
		new Thread(){
			public void run(){
				try {
					Thread.sleep(10000l);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				Notify.on(new Notify.Listener(){
					@Override
					public <T> void execute(String message) {
						Map params = Utils.eval(message);
						String to = (String) params.get("to");
						if(to==null || to.equals("*")){
							CometServlet.send(params);
						}else{
							for(String id:to.split(",")){
								String sid = Cache.defaultRedisSupport.getValue("USID", id);
								CometServlet.send(params,sid);
							}
						}
					}
				}, "admin.comet");
			}
		}.start();		
	}
	

}